#ifndef _DBBSTRING_H_
#define _DBBSTRING_H_

#include "dbb.h"

//==============================================================================
// basic fast string class
//==============================================================================
class String
{
public:
	//inner string ref counter struct
	struct Rep
	{
		inline char*		getData();
		inline const char*	getData() const;
		inline char*		refCopy();
		inline dbbsize		getSize() const;
		inline void			unRef();
		void				freeMemory();
		Rep*				clone() const;
		static Rep*			Create(dbbsize slen);
		dbbsize m_length;
		dbbsize m_capacity;
		dbbsize m_references;
	};

public:
	//con/destructor
	String();
	String(const char* s);
	String(const char* b, dbbsize len);
	String(const String& s);
	~String();
	
	void			operator=(const String& s);
	void			operator=(const char*);

	//common access
	char			operator[](dbbindex i) const;
	void			printf(const char* format, ...);
	dbbindex		indexOf(char c, dbbindex startIndex=0, dbbindex endIndex=InvalidIndex) const;
	dbbindex		lastIndexOf(char c, dbbindex startIndex=0, dbbindex endIndex=InvalidIndex) const;

	const char*		cString() const;

	//compare
	int				compareTo(const String& other) const;
	int				compareTo(const char* other) const;
	int				compareToIgnoreCase(const String& other) const;
	int				compareToIgnoreCase(const char* other) const;

	friend bool		operator< (const String& lhs, const String& rhs);
	friend bool		operator> (const String& lhs, const String& rhs);
	friend bool		operator==(const String& lhs, const String& rhs);
	friend bool		operator!=(const String& lhs, const String& rhs);
	
	friend bool		operator==(const String& lhs, const char* rhs);
	friend bool		operator==(const char* lhs, const String& rhs);
	friend bool		operator!=(const String& lhs, const char* rhs);
	friend bool		operator!=(const char* lhs, const String& rhs);

	//method
	bool			beginsWith(const String& s) const;
	bool			beginsWith(const char* s) const;
	bool			endsWith(const String& s) const;
	bool			endsWith(const char* s) const;

	void			operator+=(const String& other);
	void			operator+=(const char* other);
	friend String	operator+(const String& lhs, const String& rhs);
	friend String	operator+(const String& lhs, const char* rhs);

	dbbsize			getLength() const;

	String			replace(char from, char to) const;
	String			replaceAll(char from, char to) const;
	String			replace(const String& from, const String& to) const;
	String			replaceAll(const String& from, const String& to) const;

	String			asUpperCase() const;
	String			asLowerCase() const;

	String			substr(dbbindex index, dbbindex maxChars=InvalidIndex) const;

private:
	explicit		String(Rep* r);
	Rep&			_getRep() const;
	char*			m_string;
	static char		s_emptyStringRep[sizeof(int)+sizeof(int)+sizeof(int)+sizeof(char)];
	static Rep&		_GetEmptyStringRep();

public:
	static char		ToUpper(char c);
	static char		ToLower(char c);

	static dbbsize	Snprintf(char* buf, dbbsize n, const char* fmt, ...);
	static dbbsize	Vsnprintf(char* buf, dbbsize len, const char* fmt, void* args);
	static dbbsize	Sprintf(char* buf, const char* fmt, ...);
	
	static int		StrCmp(const char* lhs, const char* rhs);
	static int		StrNcmp(const char* lhs, const char* rhs, dbbsize n);
	static int		StrCasecmp(const char* lhs, const char* rhs);
	static int		StrNcasecmp(const char* lhs, const char* rhs, dbbsize n);

	static void		StrCpy(char* dst, const char* src);
	static void		StrNcpy(char* dst, const char* src, dbbsize n);
	
	static dbbsize	StrLen(const char* src);

	static int		Atoi(const char* in);
	static float	Atof(const char* in);

	static const char*	StrStr(const char* haystack, const char* needle);
	static const char*	StrChr(const char* haystack, char needle);
	static const char*	StrRchr(const char* haystack, char needle);

	static char*	StrDup(const char* src);
	static char*	StrNdup(const char* src, dbbsize maxLen);
	static char*	StrLwr(char* src);
	static char*	StrUpr(char* src);

	static void		MemCpy(void* dst, const void* src, dbbsize n);
	static void		MemMove(void* dst, const void* src, dbbsize n);
	static void		MemSet(void* dst, const int c, dbbsize n);
	static int		MemCmp(const void* buf1, const void* buf2, dbbsize n);

};

#include "util/dbbstring.inl"

#endif